#ifndef LONGKEY_BREAKPAD_PROCESSOR_STACK_FRAME_H_
#define LONGKEY_BREAKPAD_PROCESSOR_STACK_FRAME_H_

#include <string>

class CodeModule;

using std::string;

struct StackFrame
{
	// Indicates how well the instruction pointer derived during
	// stack walking is trusted. Since the stack walker can resort to
	// stack scanning, it can wind up with dubious frames.
	// In rough order of "trust metric".
	enum FrameTrust
	{
		FRAME_TRUST_NONE,     // Unknown
		FRAME_TRUST_SCAN,     // Scanned the stack, found this
		FRAME_TRUST_CFI_SCAN, // Scanned the stack using call frame info, found this
		FRAME_TRUST_FP,       // Derived from frame pointer
		FRAME_TRUST_CFI,      // Derived from call frame info
		FRAME_TRUST_CONTEXT   // Given as instruction pointer in a context
	};

	StackFrame()
		: instruction(),
		module(NULL),
		function_name(),
		function_base(),
		source_file_name(),
		source_line(),
		source_line_base(),
		trust(FRAME_TRUST_NONE) {}
	virtual ~StackFrame() {}

	// Return a string describing how this stack frame was found
	// by the stackwalker.
	string trust_description() const
	{
		switch (trust)
		{
		case StackFrame::FRAME_TRUST_CONTEXT:
			return "given as instruction pointer in context";
		case StackFrame::FRAME_TRUST_CFI:
			return "call frame info";
		case StackFrame::FRAME_TRUST_CFI_SCAN:
			return "call frame info with scanning";
		case StackFrame::FRAME_TRUST_FP:
			return "previous frame's frame pointer";
		case StackFrame::FRAME_TRUST_SCAN:
			return "stack scanning";
		default:
			return "unknown";
		}
	};

	// The program counter location as an absolute virtual address.  For the
	// innermost called frame in a stack, this will be an exact program counter
	// or instruction pointer value.  For all other frames, this will be within
	// the instruction that caused execution to branch to a called function,
	// but may not necessarily point to the exact beginning of that instruction.
	u_int64_t instruction;

	// The module in which the instruction resides.
	const CodeModule *module;

	// The function name, may be omitted if debug symbols are not available.
	string function_name;

	// The start address of the function, may be omitted if debug symbols
	// are not available.
	u_int64_t function_base;

	// The source file name, may be omitted if debug symbols are not available.
	string source_file_name;

	// The (1-based) source line number, may be omitted if debug symbols are
	// not available.
	int source_line;

	// The start address of the source line, may be omitted if debug symbols
	// are not available.
	u_int64_t source_line_base;

	// Amount of trust the stack walker has in the instruction pointer
	// of this frame.
	FrameTrust trust;
};

#endif	// LONGKEY_BREAKPAD_PROCESSOR_STACK_FRAME_H_